package com.github.kezhenxu94.playground.java.concurrent.executor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * <pre>
 * 
 * {@link java.util.concurrent.Executor} 接口实现了
 * 将任务的提交和任务是如何运行的相解耦, 但是 Executor 没有
 * 提供用于管理 Executor 生命周期的任何方法, 而 Executor
 * 执行任务的时候使用的线程并非守护线程, 因此执行完所有提交的
 * 任务后除非强制关闭 JVM 否则无法关闭 Executor. 
 * 
 * {@link java.util.concurrent.ExecutorService} 接
 * 口扩展了 Executor 接口, 该接口提供了可以管理 Executor
 * 生命周期的方法, 如 {@code ExecutorService#shutdown()}
 * 还提供了用来判断 Executor 状态的方法, 如 
 * {@code ExecutorService#isShutdown()}
 * 
 * {@link java.util.concurrent.ExecutorService} 接
 * 口还提供了其他提交任务的方法, 这些方法可以返回一个
 * {@link java.util.concurrent.Future} 对象, 用来获取
 * 任务执行的结果. 
 * 
 * {@link java.util.concurrent.ExecutorService} 几个
 * 主要方法：
 * 1. {@link ExecutorService#submit(Runnable)} 提交
 * 一个 Runnable 表示的任务, 该方法返回一个 Future<?>, 可
 * 以通过该 {@link Future#get()} 方法等待该任务完成, 或者
 * 通过 {@link Future#get(long, TimeUnit)} 在指定的时
 * 间内等待该任务完成, 这两个方法始终返回 null.
 * 
 * 2. {@link ExecutorService#submit(Runnable, Object)} 
 * 同上, 不过可以通过第二个参数指定在该任务完成后, 通过 
 * {@link Future#get()} 方法可以获取的结果.
 * 
 * 3. {@link ExecutorService#submit(Callable)} 提交
 * 一个 {@link Callable} 表示的任务, 同样返回一个 Future<?>
 * 对象, {@link Future#get()} 方法返回的对象是该 Callable
 * 对象的 {@link Callable#call()} 返回的.
 * 
 * </pre>
 * 
 * @author kezhenxu
 */
public class StudyExecutorService {
	
	public static void main(String[] args) throws Exception {
		ExecutorService executor = Executors.newCachedThreadPool();
		for (int i = 0; i < 100; i++) {
			executor.execute(() -> System.out.println(Thread.currentThread().getName()));
		}
		// 从输出可以看出, 有多个线程被重用了, 避免重复创建消除线程
		
		List<Future<?>> result = new ArrayList<>();
		for (int i = 0; i < 100; i++) {
			Future<?> future = executor.submit(() -> {
			});
			result.add(future);
		}
		for (Future<?> future : result) {
			System.out.println(future.get());
		}
		// 提交 Runnable, future.get() 结果都是 null
		
		result.clear();
		for (int i = 0; i < 100; i++) {
			Future<?> future = executor.submit(() -> {
			}, i);
			result.add(future);
		}
		for (Future<?> future : result) {
			System.out.println(future.get());
		}
		// 提交 Runnable, 第二个参数 i 是该任务结束后, 对应的 future.get() 要返回的值
		
		result.clear();
		for (int i = 0; i < 100; i++) {
			Future<Long> future = executor.submit(() -> Thread.currentThread().getId());
			result.add(future);
		}
		for (Future<?> future : result) {
			System.out.println(future.get());
		}
		// 提交 Callable, future.get() 结果是 Callable.call() 的返回结果
		
		executor.shutdown();
		// 关闭 Executor
	}
}
